#include "lcd.h"
#include "lcd_init.h"
#include "lcd_font.h"

/******************************************************************************
	  函数说明：在指定区域填充颜色
	  入口数据：xsta,ysta   起始坐标
				xend,yend   终止坐标
								color       要填充的颜色
	  返回值：  无
******************************************************************************/
void LCD_Fill(u16 xsta, u16 ysta, u16 xend, u16 yend, u16 color)
{
	u16 i, j;
	LCD_Address_Set(xsta, ysta, xend - 1, yend - 1); // 设置显示范围
	for (i = ysta; i < yend; i++)
	{
		for (j = xsta; j < xend; j++)
		{
			LCD_WR_DATA(color);
		}
	}
}

/******************************************************************************
	  函数说明：在指定位置画点
	  入口数据：x,y 画点坐标
				color 点的颜色
	  返回值：  无
******************************************************************************/
void LCD_DrawPoint(u16 x, u16 y, u16 color)
{
	LCD_Address_Set(x, y, x, y); // 设置光标位置
	LCD_WR_DATA(color);
}

/******************************************************************************
	  函数说明：画线
	  入口数据：x1,y1   起始坐标
				x2,y2   终止坐标
				color   线的颜色
	  返回值：  无
******************************************************************************/
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
	u16 t;
	int xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int incx, incy, uRow, uCol;
	delta_x = x2 - x1; // 计算坐标增量
	delta_y = y2 - y1;
	uRow = x1; // 画线起点坐标
	uCol = y1;
	if (delta_x > 0)
		incx = 1; // 设置单步方向
	else if (delta_x == 0)
		incx = 0; // 垂直线
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}
	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; // 水平线
	else
	{
		incy = -1;
		delta_y = -delta_x;
	}
	if (delta_x > delta_y)
		distance = delta_x; // 选取基本增量坐标轴
	else
		distance = delta_y;
	for (t = 0; t < distance + 1; t++)
	{
		LCD_DrawPoint(uRow, uCol, color); // 画点
		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

/******************************************************************************
	  函数说明：画矩形
	  入口数据：x1,y1   起始坐标
				x2,y2   终止坐标
				color   矩形的颜色
	  返回值：  无
******************************************************************************/
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
	LCD_DrawLine(x1, y1, x2, y1, color);
	LCD_DrawLine(x1, y1, x1, y2, color);
	LCD_DrawLine(x1, y2, x2, y2, color);
	LCD_DrawLine(x2, y1, x2, y2, color);
}

/******************************************************************************
	  函数说明：画圆
	  入口数据：x0,y0   圆心坐标
				r       半径
				color   圆的颜色
	  返回值：  无
******************************************************************************/
void Draw_Circle(u16 x0, u16 y0, u8 r, u16 color)
{
	u16 a, b;
	a = 0;
	b = r;
	while (a <= b)
	{
		LCD_DrawPoint(x0 - b, y0 - a, color); // 3
		LCD_DrawPoint(x0 + b, y0 - a, color); // 0
		LCD_DrawPoint(x0 - a, y0 + b, color); // 1
		LCD_DrawPoint(x0 - a, y0 - b, color); // 2
		LCD_DrawPoint(x0 + b, y0 + a, color); // 4
		LCD_DrawPoint(x0 + a, y0 - b, color); // 5
		LCD_DrawPoint(x0 + a, y0 + b, color); // 6
		LCD_DrawPoint(x0 - b, y0 + a, color); // 7
		a++;
		if ((a * a + b * b) > (r * r)) // 判断要画的点是否过远
		{
			b--;
		}
	}
}

/******************************************************************************
	  函数说明：显示单个字符
	  入口数据：x,y显示坐标
				num 要显示的字符
				fc 字的颜色
				bc 字的背景色
				sizey 字号
				mode:  0非叠加模式  1叠加模式
	  返回值：  无
******************************************************************************/
void LCD_ShowChar(u16 x, u16 y, u8 num, u16 fc, u16 bc, u8 sizey)
{
	if(16 == sizey) {
		LCD_ShowChar16(x,y,num,fc,bc);
	} else {
		LCD_ShowChar32(x,y,num, fc,bc);
	}
}

void LCD_ShowChar16(u16 x, u16 y, u8 num, u16 fc, u16 bc)
{
	u8 temp, t, num1;
	u8 i; // 一个字符所占字节大小
	u16 x0 = x;
	num1 = num - ' ';
	LCD_Address_Set(x, y, x + 7, y + 15); // 设置光标位置
	for (i = 0; i < 16; i++)
	{
		temp = ascii_1608[num1][i]; // 调用8x16字体
		for (t = 0; t < 8; t++)
		{
			if (temp & (0x01 << t))
				{
					LCD_WR_DATA(fc);
				}
				else
				{
					LCD_WR_DATA(bc);
				}
		}
	}
}

void LCD_ShowChar32(u16 x, u16 y, u8 num, u16 fc, u16 bc)
{
	u8 temp, t;
	u16 i; // 一个字符所占字节大小
	u16 x0 = x;
	num=num-' ';    //得到偏移后的值

	// LCD_Address_Set(x, y, x + sizex - 1, y + sizey - 1); // 设置光标位置
	LCD_Address_Set(x, y, x + 15, y + 31);
	for (i = 0; i < 64; i++)
	{
		temp = ascii_3216[num][i]; // 调用16x32字体
		for (t = 0; t < 8; t++)
		{
			if (temp & (0x01 << t))
				{
					LCD_WR_DATA(fc);
				}
				else
				{
					LCD_WR_DATA(bc);
				}
		}
	}
}

/******************************************************************************
	  函数说明：显示字符串
	  入口数据：x,y显示坐标
				*p 要显示的字符串
				fc 字的颜色
				bc 字的背景色
				sizey 字号
				mode:  0非叠加模式  1叠加模式
	  返回值：  无
******************************************************************************/
void LCD_ShowString(u16 x, u16 y, const u8 *p, u16 fc, u16 bc, u8 sizey)
{
	while (*p != '\0')
	{
		if(16 == sizey) {
			LCD_ShowChar16(x, y, *p, fc, bc);
			x += 8;
		} else 
		{
			LCD_ShowChar32(x, y, *p, fc, bc);
			x += 16;
		}
	
		p++;
	}
}

/******************************************************************************
	  函数说明：显示数字
	  入口数据：m底数，n指数
	  返回值：  无
******************************************************************************/
u32 mypow(u8 m, u8 n)
{
	u32 result = 1;
	// if(n <= 0) {
	// 	return result;
	// }
	while (n-- > 0) {
		result *= m;
	}
	return result;
}

/******************************************************************************
	  函数说明：显示整数变量
	  入口数据：x,y显示坐标
				num 要显示整数变量
				len 要显示的位数
				fc 字的颜色
				bc 字的背景色
				sizey 字号
	  返回值：  无
******************************************************************************/
void LCD_ShowIntNum(u16 x,u16 y, u16 num,u8 len,u16 fc,u16 bc,u16 sizey)
{         	
	u8 t;
	u8 enshow=0;
	u8 temp;
	u16 sizex = sizey / 2;
	u16 xstart = 0;
	for(t=0;t<len;t++)
	{
		xstart = x+t*sizex;
		u32 mypowr = mypow(10, len-t-1);
		temp = num/mypowr%10;
		
		if(enshow==0&&t<(len-1))
		{
			if(temp==0)
			{	
				LCD_ShowChar(xstart,y,' ',fc,bc,sizey);
				continue;
			}else enshow=1; 
		 	 
		}
	 	LCD_ShowChar(xstart,y,temp+48,fc,bc,sizey);
	}
} 

/******************************************************************************
	  函数说明：显示两位小数变量
	  入口数据：x,y显示坐标
				num 要显示小数变量
				len 要显示的位数
				fc 字的颜色
				bc 字的背景色
				sizey 字号
	  返回值：  无
******************************************************************************/
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{
	u8 t,temp,sizex;
	u16 num1;
	sizex=sizey/2;
	num1=num*100;
	for(t=0;t<len;t++)
	{
		temp=(num1/mypow(10,len-t-1))%10;
		if(t==(len-2))
		{
			LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey);
			t++;
			len+=1;
		}
	 	LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey);
	}
}

/******************************************************************************
	  函数说明：显示图片
	  入口数据：x,y起点坐标
				length 图片长度
				width  图片宽度
				pic[]  图片数组
	  返回值：  无
******************************************************************************/
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
{
	u16 i,j,k=0;
	LCD_Address_Set(x,y,x+length-1,y+width-1);
	for(i=0;i<length;i++)
	{
		for(j=0;j<width;j++)
		{
			LCD_WR_DATA8(pic[k*2]);
			LCD_WR_DATA8(pic[k*2+1]);
			k++;
		}
	}
}

void LCD_ShowWelcom(void) {
	// 这里先关闭lcd背光，等画完后再打开防止出现花屏。
	LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
	LCD_ShowString(80,40, "WELCOME!!!", GREEN, BLACK, 32);
	LCD_ShowString(64,60 + 40, "POWERD BY STC", GREEN, BLACK, 32);
	LCD_ShowString(64,60 + 80, "IC:STC8H8H64U", GREEN, BLACK, 32);
	LCD_ShowString(20,60 + 120, "https://stcai.com", GREEN, BLACK, 32);
}

void LCD_ShowIndex(void) {
	// 清屏
    LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
    // 画出边框
    LCD_Fill(0,0,LCD_W,3,GREEN);
    LCD_Fill(0,3,3,LCD_H,GREEN);
    LCD_Fill(3,LCD_H - 3,LCD_W,LCD_H,GREEN);
    LCD_Fill(LCD_W - 3,3,LCD_W,LCD_H,GREEN);
    LCD_Fill(3,43,LCD_W - 3,45,GREEN);
    LCD_Fill(3,84,LCD_W - 3 ,86,GREEN);
    LCD_Fill(156,87,158,237,GREEN);

	// 温度湿度标题
	LCD_ShowString(TEMP_LOCAL_X,TEMP_LOCAL_Y, "TEMP", WHITE, BLACK, 32);
	LCD_ShowString(HUM_LOCAL_X,HUM_LOCAL_Y, "HUM", WHITE, BLACK, 32);
	LCD_ShowChar(HUM_LOCAL_X+ 32,HUM_LOCAL_Y + 48,'%', WHITE, BLACK, 32);
}

void LCD_ShowPower(u16 power) {

	// 计算横坐标的结束位置
	u16 xend = 0;
	xend = 263+ (u32)((u32)power * 38) / 3300;
	if(xend < 270) {
		LCD_Fill(263,16,xend,32,RED);
	} else {
		LCD_Fill(263,16,xend,32,WHITE);
	}
	

	LCD_DrawRectangle(260, 13, LCD_W - 16, 13+22, WHITE); // 首先画出电池的轮廓
	LCD_Fill(LCD_W - 15, 21,LCD_W - 12, 27, WHITE);
	
	
}
